package cn.com.nes.site.modules.agent.grant;

import cn.com.nes.mybatis.agent.agent.entity.AgentGrantProduct;
import cn.com.nes.mybatis.agent.agent.entity.AgentGrantRegion;
import cn.com.nes.mybatis.agent.agent.entity.AgentGrantType;
import cn.com.nes.mybatis.agent.ope.entity.GGoods;
import cn.com.nes.mybatis.agent.system.entity.TAgentFacturer;
import cn.com.nes.mybatis.agent.system.entity.TUser;
import cn.com.nes.site.entity.em.DeleteEnum;
import cn.com.nes.site.entity.em.agent.grant.AgentGrantTypeEnum;
import cn.com.nes.site.service.agent.AgentFacturerService;
import cn.com.nes.site.service.agent.AgentGrantProductService;
import cn.com.nes.site.service.agent.AgentGrantRegionService;
import cn.com.nes.site.service.agent.AgentGrantTypeService;
import cn.com.nes.site.service.agent.bo.AgentGrantPageBO;
import cn.com.nes.site.service.agent.bo.AgentGrantQueryBO;
import cn.com.nes.site.service.agent.bo.AgentGrantSaveBO;
import cn.com.nes.site.service.agent.dto.AgentGrantDTO;
import cn.com.nes.site.service.agent.dto.AgentGrantDetailDTO;
import cn.com.nes.site.service.product.GGoodsService;
import cn.com.nes.site.service.product.dto.ProductDTO;
import cn.com.nes.site.service.system.region.XzqhService;
import cn.com.nes.site.service.system.region.dto.RegionDTO;
import cn.com.nes.site.service.system.user.SystemUserService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AgentGrant {

    @Resource
    private AgentGrantTypeService agentGrantTypeService;

    @Resource
    private AgentGrantProductService agentGrantProductService;

    @Resource
    private AgentGrantRegionService agentGrantRegionService;

    @Resource
    private SystemUserService systemUserService;

    @Resource
    private XzqhService xzqhService;

    @Resource
    private GGoodsService gGoodsService;

    @Resource
    private AgentFacturerService agentFacturerService;

    public IPage<AgentGrantDTO> getPage(AgentGrantPageBO agentGrantPageBO) throws Exception {
        LambdaQueryWrapper<AgentGrantType> wrapper = new LambdaQueryWrapper<AgentGrantType>().eq(AgentGrantType::getDeleted, DeleteEnum._0.getKey())
                .eq(AgentGrantType::getAgentRelationshipId, agentGrantPageBO.getAgentRelationshipId());
        if (ObjectUtil.isNotNull(agentGrantPageBO.getGrantType())) {
            wrapper.eq(AgentGrantType::getGrantType, agentGrantPageBO.getGrantType().getKey());
        }
        Page<AgentGrantType> page = (Page<AgentGrantType>) agentGrantTypeService.page(new Page<>(agentGrantPageBO.getPageid(), agentGrantPageBO.getPagesize()), wrapper);

        Set<Long> createrSet = page.getRecords()
                .stream()
                .map(AgentGrantType::getGmtCreateId)
                .collect(Collectors.toSet());
        List<TUser> users = systemUserService.getUsers(new ArrayList<>(createrSet));

        Map<Long, String> userIdAndNameMap = users.stream().collect(Collectors.toMap(TUser::getId, TUser::getUsername));

        return page.convert(record -> {
            AgentGrantDTO agentGrantDTO = new AgentGrantDTO();
            BeanUtils.copyProperties(record, agentGrantDTO);
            agentGrantDTO.setGrantTypeName(AgentGrantTypeEnum.enumConvertKeyToValue(String.valueOf(record.getGrantType())));
            agentGrantDTO.setGmtCreateName(userIdAndNameMap.get(record.getGmtCreateId()));
            long diffMillis = record.getEndTime().getTime() - System.currentTimeMillis();
            agentGrantDTO.setRemainDays(diffMillis / (1000 * 60 * 60 * 24));
            return agentGrantDTO;
        });
    }

    public AgentGrantDetailDTO getDetail(AgentGrantQueryBO agentGrantQueryBO) {
        AgentGrantType grantType = agentGrantTypeService.getOne(new LambdaQueryWrapper<AgentGrantType>().eq(AgentGrantType::getGrantId, agentGrantQueryBO.getGrantId()));
        if (ObjectUtil.isNull(grantType)) {
            return null;
        }

        TUser operateUser = systemUserService.getById(grantType.getGmtCreateId());
        // 构建并返回 DTO
        AgentGrantDetailDTO dto = new AgentGrantDetailDTO();
        BeanUtils.copyProperties(grantType, dto);
        dto.setGrantTypeName(AgentGrantTypeEnum.enumConvertKeyToValue(String.valueOf(dto.getGrantType())));
        dto.setGmtCreateName(operateUser.getNickName());
        long diffMillis = dto.getEndTime().getTime() - System.currentTimeMillis();
        dto.setRemainDays(diffMillis / (1000 * 60 * 60 * 24));

        // 查询产品授权
        List<String> productUuids = agentGrantProductService.listObjs(new LambdaQueryWrapper<AgentGrantProduct>().select(AgentGrantProduct::getProductUuid)
                .eq(AgentGrantProduct::getDeleted, DeleteEnum._0.getKey())
                .eq(AgentGrantProduct::getGrantId, agentGrantQueryBO.getGrantId()), obj -> (String) obj);
        List<ProductDTO> productList = gGoodsService.getGoods(productUuids);
        dto.setGrantProductList(productList);

        // 查询区域授权
        List<String> regionCodes = agentGrantRegionService.listObjs(new LambdaQueryWrapper<AgentGrantRegion>().select(AgentGrantRegion::getRegionCode)
                .eq(AgentGrantRegion::getDeleted, DeleteEnum._0.getKey())
                .eq(AgentGrantRegion::getGrantId, agentGrantQueryBO.getGrantId()), obj -> (String) obj);
        List<RegionDTO> regionList = xzqhService.getRegionCodes(regionCodes);
        dto.setGrantRegionList(regionList);
        return dto;
    }

    public AgentGrantType saveAgentGrant(AgentGrantSaveBO agentGrantSaveBO) {
        AgentGrantType agentGrantType = buildAgentGrantType(agentGrantSaveBO);
        agentGrantTypeService.saveOrUpdate(agentGrantType);

        agentGrantProductService.remove(new LambdaQueryWrapper<AgentGrantProduct>().eq(AgentGrantProduct::getGrantId, agentGrantSaveBO.getGrantId()));
        List<AgentGrantProduct> grantProducts = buildGrantProducts(agentGrantSaveBO, agentGrantType);
        if (CollUtil.isNotEmpty(grantProducts)) {
            agentGrantProductService.saveBatch(grantProducts);
        }

        agentGrantRegionService.remove(new LambdaQueryWrapper<AgentGrantRegion>().eq(AgentGrantRegion::getGrantId, agentGrantSaveBO.getGrantId()));
        List<AgentGrantRegion> grantRegions = buildAgentGrantRegion(agentGrantSaveBO, agentGrantType);
        if (CollUtil.isNotEmpty(grantRegions)) {
            agentGrantRegionService.saveBatch(grantRegions);
        }

        return agentGrantType;
    }

    private List<AgentGrantRegion> buildAgentGrantRegion(AgentGrantSaveBO agentGrantSaveBO,
            AgentGrantType agentGrantType) {
        if (CollUtil.isEmpty(agentGrantSaveBO.getRegionCodeList())) {
            return Collections.emptyList();
        }
        List<AgentGrantRegion> agentGrantRegions = new ArrayList<>();
        for (String regionCode : agentGrantSaveBO.getRegionCodeList()) {
            AgentGrantRegion agentGrantRegion = new AgentGrantRegion();
            agentGrantRegion.setRegionCode(regionCode);
            agentGrantRegion.setGrantId(agentGrantType.getGrantId());
            agentGrantRegion.setDeleted(DeleteEnum._0.getKey());
            agentGrantRegion.setGmtCreate(agentGrantSaveBO.getOperateDate());
            agentGrantRegion.setGmtCreateId(agentGrantSaveBO.getOperateUserId());
            agentGrantRegions.add(agentGrantRegion);
        }
        return agentGrantRegions;
    }

    private List<AgentGrantProduct> buildGrantProducts(AgentGrantSaveBO agentGrantSaveBO,
            AgentGrantType agentGrantType) {
        List<AgentGrantProduct> grantProducts = new ArrayList<>();
        for (String productUuid : agentGrantSaveBO.getProductUuidList()) {
            AgentGrantProduct agentGrantProduct = new AgentGrantProduct();
            agentGrantProduct.setProductUuid(productUuid);
            agentGrantProduct.setGrantId(agentGrantType.getGrantId());
            agentGrantProduct.setDeleted(DeleteEnum._0.getKey());
            agentGrantProduct.setGmtCreate(agentGrantSaveBO.getOperateDate());
            agentGrantProduct.setGmtCreateId(agentGrantSaveBO.getOperateUserId());
            grantProducts.add(agentGrantProduct);
        }
        return grantProducts;
    }

    @NotNull
    private static AgentGrantType buildAgentGrantType(AgentGrantSaveBO agentGrantSaveBO) {
        if (ObjectUtil.isNotNull(agentGrantSaveBO.getGrantId())) {
            agentGrantSaveBO.setUpdate(true);
        }
        AgentGrantType agentGrantType = new AgentGrantType();
        if (agentGrantSaveBO.isUpdate()) {
            agentGrantType.setGrantId(agentGrantSaveBO.getGrantId());
            agentGrantType.setGmtModifiedId(agentGrantSaveBO.getOperateUserId());
            agentGrantType.setGmtModified(agentGrantSaveBO.getOperateDate());
        } else {
            agentGrantType.setGmtCreateId(agentGrantSaveBO.getOperateUserId());
            agentGrantType.setGmtCreate(agentGrantSaveBO.getOperateDate());
            agentGrantType.setDeleted(DeleteEnum._0.getKey());
        }
        agentGrantType.setAgentRelationshipId(agentGrantSaveBO.getAgentRelationshipId());
        agentGrantType.setGrantType(Integer.parseInt(agentGrantSaveBO.getGrantType().getKey()));
        agentGrantType.setStartTime(agentGrantSaveBO.getStartTime());
        agentGrantType.setEndTime(agentGrantSaveBO.getEndTime());
        return agentGrantType;
    }

    public List<GGoods> getGrantProductNode(String operateUserCompanyId) {
        if (StrUtil.isEmpty(operateUserCompanyId)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<TAgentFacturer> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TAgentFacturer::getDeleted, DeleteEnum._0.getKey());
        queryWrapper.eq(TAgentFacturer::getAgentId, operateUserCompanyId);
        List<TAgentFacturer> agentFacturers = agentFacturerService.list(queryWrapper);
        if (CollUtil.isEmpty(agentFacturers)) {
            return Collections.emptyList();
        }

        // 查询授权类型
        LambdaQueryWrapper<AgentGrantType> grantTypeQueryWrapper = new LambdaQueryWrapper<>();
        grantTypeQueryWrapper.eq(AgentGrantType::getDeleted, DeleteEnum._0.getKey());
        grantTypeQueryWrapper.eq(AgentGrantType::getGrantType, AgentGrantTypeEnum.SALE.getKey());
        grantTypeQueryWrapper.in(AgentGrantType::getAgentRelationshipId, agentFacturers.stream().map(TAgentFacturer::getAgentId).collect(Collectors.toList()));
        List<AgentGrantType> agentGrantTypes = agentGrantTypeService.list(grantTypeQueryWrapper);
        if (CollUtil.isEmpty(agentGrantTypes)) {
            return Collections.emptyList();
        }

        // 查询产品授权
        LambdaQueryWrapper<AgentGrantProduct> grantProductQueryWrapper = new LambdaQueryWrapper<>();
        grantProductQueryWrapper.eq(AgentGrantProduct::getDeleted, DeleteEnum._0.getKey());
        grantProductQueryWrapper.in(AgentGrantProduct::getGrantId, agentGrantTypes.stream().map(AgentGrantType::getGrantId).collect(Collectors.toList()));
        List<AgentGrantProduct> agentGrantProducts = agentGrantProductService.list(grantProductQueryWrapper);
        if (CollUtil.isEmpty(agentGrantProducts)) {
            return Collections.emptyList();
        }

        // 查询产品
        LambdaQueryWrapper<GGoods> goodsQueryWrapper = new LambdaQueryWrapper<>();
        goodsQueryWrapper.in(GGoods::getUuid, agentGrantProducts.stream().map(AgentGrantProduct::getProductUuid).collect(Collectors.toList()));
        return gGoodsService.list(goodsQueryWrapper);
    }

    public List<Long> getGrantBrandNode(String operateUserCompanyId) {
        if (StrUtil.isEmpty(operateUserCompanyId)) {
            return Collections.emptyList();
        }
        List<GGoods> goods = this.getGrantProductNode(operateUserCompanyId);
        if (CollUtil.isEmpty(goods)) {
            return Collections.emptyList();
        }
        return goods.stream().map(GGoods::getBrandId).collect(Collectors.toList());
    }

    public List<String> queryAgentSupplierIds(Long callCenterCompanyId) {
        return agentFacturerService.queryAgentSupplierIds(callCenterCompanyId);
    }
}
